package com.cman777.springc.mybatis.sqinjector.method;

import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;

/**
 * @author chenzhicong
 * @time 2020/3/18 1:05
 * @description AbstractMethod修改所有字段，null也更新，但是不包含逻辑删除字段与创建时间字段
 */
public class UpdateAllColumnById extends AbstractMethod {
    private static final String METHOD_NAME = "updateAllColumnById";
    /**
      * 存放对tableField的过滤条件
      */
    private volatile static List<Predicate<TableFieldInfo>> predicates
            = new LinkedList<>();
    static {
        // 忽略逻辑字段
        predicates.add(t-> !t.isLogicDelete());
        // 忽略创建时间
        predicates.add(t-> !t.getColumn().equals("created_date"));
    }
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;
        final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);
        String sqlSet = this.filterTableFieldInfo(tableInfo.getFieldList(), getPredicate(),
                i -> i.getSqlSet(true, ENTITY_DOT), NEWLINE);
        sqlSet = SqlScriptUtils.convertSet(sqlSet);
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet,
                tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addUpdateMappedStatement(mapperClass, modelClass, METHOD_NAME, sqlSource);
    }

    /**
      * 遍历predicates，只要一个返回false那么就是false
      */
    public Predicate<TableFieldInfo> getPredicate(){
        return t->{
            for (Predicate<TableFieldInfo> predicate : predicates) {
                if(!predicate.test(t)){
                    return false;
                }
            }
            return true;
        };
    }



}
